package com.tencent.sr.iris.activity.dependency.qufa;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.RateLimiter;
import com.tencent.sr.iris.activity.common.config.*;
import com.tencent.sr.iris.activity.common.constant.QuFaHttpConstant;
import com.tencent.sr.iris.activity.common.util.QuFaHttpUtil;
import com.tencent.sr.iris.activity.common.util.QuFaStaticHttpUtil;
import com.tencent.sr.iris.activity.dependency.dto.activity.QueryAwardReceiveListDTO;
import com.tencent.sr.iris.activity.dependency.dto.activity.TaskIncomeDTO;
import com.tencent.sr.iris.activity.interfaces.dto.SceneInfoMappingDTO;
import com.tencent.sr.iris.activity.interfaces.request.acticity.QuFaCheckHasJoinSpecialPromoteRequest;
import com.tencent.sr.iris.activity.interfaces.request.acticity.QuFaUserHasJoinNormalPromoteRequest;
import com.tencent.sr.iris.activity.interfaces.request.acticity.QueryAwardReceiveListRequest;
import com.tencent.sr.iris.activity.interfaces.request.task.*;
import com.tencent.sr.iris.activity.interfaces.response.group.task.*;
import com.tencent.sr.rmall.common.request.PaginationRequest;
import com.tencent.sr.rmall.common.response.PaginationResponse;
import com.tencent.sr.rmall.springbootstarter.utils.BeanCopierUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class GroupTaskDependency {


    @Resource
    private QuFaHttpUtil quFaHttpUtil;

    //    @Resource(name = "quFaDataConfig")
    @Autowired
    @Qualifier(value = "quFaDataConfig")
    private QuFaDataConfig quFaDataConfig;

    @Resource
    private QufaSignConfig qufaSignConfig;

    @Resource
    private ScrmServerConfig scrmServerConfig;

    @Resource
    private DependencyConfig dependencyConfig;

    private RateLimiter QUFA_QUERYAWARDRECEIVELIST_RATELIMITER = RateLimiter.create(20);

    /**
     * 是否有可参加的任务
     *
     * @return
     */
    public GroupTaskPopResponse pop(GroupTaskPopRequest request) {
        return quFaHttpUtil.postObject(QuFaHttpConstant.GROUP_TASK_POP, request, GroupTaskPopResponse.class);
    }

    /**
     * 团长任务配置
     *
     * @return
     */
    public GroupTaskConfigResponse config() {
        return quFaHttpUtil.postObject(QuFaHttpConstant.GROUP_TASK_CONFIG, null, GroupTaskConfigResponse.class);
    }

    /**
     * 查询团长累计任务奖励
     *
     * @param unionId
     * @return
     */
    public GroupTaskRewardResponse getGroupTaskReward(String unionId) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(QuFaHttpConstant.UNION_ID_KEY, unionId);
        GroupTaskRewardResponse response = quFaHttpUtil
                .postObject(QuFaHttpConstant.GROUP_TASK_REWARD, jsonObject, GroupTaskRewardResponse.class);
        log.info("区发获取任务当月奖励 unionId:{} response:{}", unionId, response);
        return response;
    }

    /**
     * 分页查询团长任务奖励明细
     *
     * @return
     */
    public PaginationResponse<GroupTaskRewardDetailResponse> pageGroupTaskRewardList(
            PaginationRequest<GroupTaskRewardDetailRequest> request) {
        PaginationResponse<GroupTaskRewardDetailResponse> response = quFaHttpUtil
                .postPage(QuFaHttpConstant.GROUP_TASK_DETAIL_LIST, request, GroupTaskRewardDetailResponse.class);
        log.info("区发分页获取任务奖励明细, unionId:{} response:{}", request.getQueryCriteria().getUnionId(), response);
        return response;
    }

    /**
     * 分页查询团长任务列表--进行中
     *
     * @return
     */
    public List<GroupTaskListResponse> listInProgress(GroupTaskListNewRequest request) {
        String url = QuFaHttpConstant.GROUP_TASK_IN_PROGRESS;

        return quFaHttpUtil.postList(url, request, GroupTaskListResponse.class);
    }

    /**
     * 分页查询团长任务列表--已结束
     *
     * @return
     */
    public PaginationResponse<GroupTaskListResponse> listEnded(PaginationRequest<GroupTaskListNewRequest> request) {
        String url = QuFaHttpConstant.GROUP_TASK_ENDED;

        return quFaHttpUtil.postPage(url, request, GroupTaskListResponse.class);
    }

    /**
     * 查询团长任务列表营销日历——营销中台
     *
     * @param request
     * @return
     */
    public List<GroupTaskListResponse> marketCalendarList(MarketTaskQuFaRequest request) {
        String url = QuFaHttpConstant.MARKET_CALENDAR_LIST;

        return quFaHttpUtil.postList(url, request, GroupTaskListResponse.class);
    }

    /**
     * //用户分层-用户下单情况
     * 1-新用户、2-首单、3-二单、4-活跃用户（二单以上）
     *
     * @param request
     * @return
     */
    @SneakyThrows
    public UserPaymentResponse queryUserPaymentInfo(UserRequest request) {
        UserPaymentResponse response = null;
        try {
            response = QuFaStaticHttpUtil.postReslutObject(BeanCopierUtil.copy(quFaDataConfig, QuFaConfig.class),
                    QuFaHttpConstant.USER_PAYMENT_INFO, request, UserPaymentResponse.class);
            log.info("注册有礼活动查询区分云选新用户接口成功,request:{},response:{}", JSON.toJSONString(request),
                    JSON.toJSONString(response));
            return response;
        } catch (Exception e) {
            log.error("注册有礼活动查询区分云选新用户接口异常,request:{},response:{}", JSON.toJSONString(request),
                    JSON.toJSONString(response), e);
            throw e;
        }

    }

    /**
     * //查询自购gmv
     *
     * @param request
     * @return
     */
    @SneakyThrows
    public PaginationResponse<QuerySelfBuyGMVResponse> queryUserSelfBuyGMV(QuerySelfBuyGMVReq request) {
        PaginationResponse<QuerySelfBuyGMVResponse> response = null;
        try {
            response = QuFaStaticHttpUtil
                    .newPageList(BeanCopierUtil.copy(quFaDataConfig, QuFaConfig.class), QuFaHttpConstant.USER_GMV_INFO,
                            request, QuerySelfBuyGMVResponse.class);
            log.info("查询自购gmv接口成功,request:{},response:{}", JSON.toJSONString(request), JSON.toJSONString(response));
            return response;
        } catch (Exception e) {
            log.error("查询自购gmv接口异常,request:{},response:{}", JSON.toJSONString(request), JSON.toJSONString(response), e);
            throw e;
        }

    }

    /**
     * 查询个人业绩
     *
     * @param quFaReq
     * @return
     */
    @SneakyThrows
    public PaginationResponse<QuFaPerformancePersonalRes> personalPerformanceList(PersonalPerformanceReq quFaReq) {

        PaginationResponse<QuFaPerformancePersonalRes> quFaResPage = null;
        try {
            quFaResPage = QuFaStaticHttpUtil.newPostPageList(BeanCopierUtil.copy(quFaDataConfig, QuFaConfig.class),
                    QuFaHttpConstant.NEW_PERSONAL_PERFORMANCE, quFaReq, QuFaPerformancePersonalRes.class);
            log.info("queryCommissionInfo.personalPerformanceList success request:{},response:{}",
                    JSON.toJSONString(quFaReq), JSON.toJSONString(quFaResPage));
        } catch (Exception e) {
            log.error("queryCommissionInfo.personalPerformanceList error request:{}", JSON.toJSONString(quFaReq), e);
            throw e;
        }
        return quFaResPage;
    }

    /**
     * 查询首单信息
     *
     * @param quFaReq
     * @return
     */
    @SneakyThrows
    public FirstOrderInfoRes firstOrderInfo(FirstOrderInfoReq quFaReq) {
        FirstOrderInfoRes firstOrderInfoRes = null;
        try {
            firstOrderInfoRes = QuFaStaticHttpUtil.postReslutObject(BeanCopierUtil.copy(quFaDataConfig, QuFaConfig.class),
                    QuFaHttpConstant.FIRST_ORDER_INFO, quFaReq, FirstOrderInfoRes.class);
            log.info("firstOrderInfo success request:{},response:{}",
                    JSON.toJSONString(quFaReq), JSON.toJSONString(firstOrderInfoRes));
        } catch (Exception e) {
            log.error("firstOrderInfo error request:{}", JSON.toJSONString(quFaReq), e);
            throw e;
        }
        return firstOrderInfoRes;
    }

    /**
     * 获取有效分享数
     *
     * @param quFaReq
     * @return
     */
    @SneakyThrows
    public List<QuFaUserShareRes> queryUsersShareVisit(UserShareRequest quFaReq) {
        List<QuFaUserShareRes> quFaResPage = QuFaStaticHttpUtil
                .postReslutList(BeanCopierUtil.copy(quFaDataConfig, QuFaConfig.class),
                        QuFaHttpConstant.USER_SHARE_VISIT_NEW, quFaReq, QuFaUserShareRes.class);
        return quFaResPage;
    }

    /**
     * 查询全量用户数据
     *
     * @param quFaReq
     * @return
     */
    @SneakyThrows
    public PaginationResponse<AllUserRes> queryAllUsers(AllUserRequest quFaReq) {
        PaginationResponse<AllUserRes> quFaResPage = QuFaStaticHttpUtil
                .newPageList(BeanCopierUtil.copy(quFaDataConfig, QuFaConfig.class), QuFaHttpConstant.ALL_USER, quFaReq,
                        AllUserRes.class);
        return quFaResPage;
    }
    
    /**
     * 是否有新人专区领券资格
     *
     * @param quFaReq
     * @return
     */
    @SneakyThrows
    public SpecialAreaQualificationResponse specialAreaQualification(SpecialAreaQualificationRequest quFaReq) {
        SpecialAreaQualificationResponse quFaResPage = QuFaStaticHttpUtil
                .postReslutObject(BeanCopierUtil.copy(quFaDataConfig, QuFaConfig.class),
                        QuFaHttpConstant.SPECIAL_AREA_QUALIFICATION, quFaReq, SpecialAreaQualificationResponse.class);
        return quFaResPage;
    }

    public QuFaUserHasJoinNormalPromoteRes checkHasJoinNormalPromote(QuFaUserHasJoinNormalPromoteRequest quFaReq) {
        return quFaHttpUtil.postObject(QuFaHttpConstant.USER_HAS_JOIN_PROMOTE, signReq(quFaReq),
                QuFaUserHasJoinNormalPromoteRes.class);
    }

    public QuFaCheckHasJoinSpecialPromoteRes checkHasJoinSpecialPromote(QuFaCheckHasJoinSpecialPromoteRequest quFaReq) {
        return quFaHttpUtil.postObject(QuFaHttpConstant.CHECK_HAS_JOIN_SPECIAL_PROMOTE, signReq(quFaReq),
                QuFaCheckHasJoinSpecialPromoteRes.class);
    }


    public QuFaAwardSendRes awardSend(RewardSendRequest quFaReq, SceneInfoMappingDTO sceneInfoMapping) {
        return quFaHttpUtil.postObject(QuFaHttpConstant.USER_PROVIDE_EQUITY, signReq(quFaReq, sceneInfoMapping),
                QuFaAwardSendRes.class);
    }

    public QuFaAwardInfoRes getAwardInfo(AwardInfoRequest quFaReq, SceneInfoMappingDTO sceneInfoMapping) {
        return quFaHttpUtil.postObject(QuFaHttpConstant.AWARD_POLL_INFO, signReq(quFaReq, sceneInfoMapping),
                QuFaAwardInfoRes.class);
    }

    public QueryOpenIdResponse queryOpenId(QueryOpenIdRequest quFaReq) {
        quFaReq.setAppkey(scrmServerConfig.getAppKey());
        String res = quFaHttpUtil.scrmRequest(QuFaHttpConstant.QUERY_OPENID_FOR_AWARD, JSONObject.toJSONString(quFaReq),
                quFaHttpUtil.HTTP_METHOD_POST);
        if (StringUtils.isNotBlank(res)) {
            ScrmResponse scrmResponse = JSONObject.parseObject(res, ScrmResponse.class);
            if (StringUtils.isNotEmpty(scrmResponse.getData())) {
                return JSONObject.parseObject(scrmResponse.getData(), QueryOpenIdResponse.class);
            }
        }
        return null;
    }

    @SneakyThrows
    private TreeMap<String, Object> signReq(Object quFaReq) {
        TreeMap<String, Object> treeMap = JSON.parseObject(JSON.toJSONString(quFaReq), TreeMap.class);
        // 每个接口是单独的配置
        String appId = qufaSignConfig.getAppId();
        String appKey = qufaSignConfig.getAppKey();
        treeMap.put("app_id", appId);
        treeMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
        treeMap.put("app_key", appKey);
        String bodySign = MD5.create().digestHex(JSON.toJSONString(treeMap));
        treeMap.put("signature", bodySign);

        return treeMap;
    }

    public TreeMap<String, Object> signReq(Object qufaReq, SceneInfoMappingDTO sceneInfoMapping) {
        TreeMap<String, Object> treeMap = JSON.parseObject(JSON.toJSONString(qufaReq), TreeMap.class);
        treeMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
        treeMap.put("app_id", sceneInfoMapping.getAppId());
        treeMap.put("app_key", sceneInfoMapping.getAppKey());
        String bodySign = MD5.create().digestHex(JSON.toJSONString(treeMap));
        treeMap.put("signature", bodySign);

        return treeMap;
    }


    @SneakyThrows
    public TaskIncomeResponse myIncome(TaskIncomeRequest request) {
        if (StrUtil.isNotBlank(request.getStartTime())) {
            request.setStartTime(DateUtil.formatDateTime(new Date(Long.parseLong(request.getStartTime()))));
        }
        if (StrUtil.isNotBlank(request.getEndTime())) {
            request.setEndTime(DateUtil.formatDateTime(new Date(Long.parseLong(request.getEndTime()))));
        }

        TaskIncomeDTO taskIncomeDTO = quFaHttpUtil
                .postObject(QuFaHttpConstant.MY_INCOME, signReq(request), TaskIncomeDTO.class);
        TaskIncomeDTO.TaskIncome taskIncome = Optional.ofNullable(taskIncomeDTO.getTaskIncome())
                .orElseGet(TaskIncomeDTO.TaskIncome::new);
        List<TaskIncomeDTO.WaitTaskPhaseData> waitTaskPhaseData = Optional
                .ofNullable(taskIncomeDTO.getWaitTaskPhaseData())
                .orElseGet(Collections::emptyList);
        TaskIncomeDTO.TaskJoinData taskJoinData = Optional.ofNullable(taskIncomeDTO.getTaskJoinData())
                .orElseGet(TaskIncomeDTO.TaskJoinData::new);
        List<TaskCommissionDetailResponse> taskList = waitTaskPhaseData.stream()
                .map(i -> new TaskCommissionDetailResponse().setTaskId(String.valueOf(i.getTaskPhaseId()))
                        .setTaskName(i.getTaskPhaseName()).setPredictAwardAmount(i.getPredictAwardAmount()))
                .collect(Collectors.toList());

        return new TaskIncomeResponse().setPredictIncome(taskIncome.getPredictIncome())
                .setTaskBonusSettlementBillAmount(taskIncome.getTaskBonusSettlementBillAmount())
                .setWaitTaskBonusSettlementBillAmount(taskIncome.getWaitTaskBonusSettlementBillAmount())
                .setGoingTaskPhaseCount(taskJoinData.getGoingTaskPhaseCount())
                .setEndedTaskPhaseCount(taskJoinData.getEndedTaskPhaseCount())
                .setWaitTaskPhaseData(taskList);
    }

    /**
     * 根据外部单号查询中奖列表
     *
     * @param outTradeNoList
     * @return
     */
    public List<QueryAwardReceiveListDTO> queryAwardReceiveList(List<String> outTradeNoList) {
        DependencyConfig.Config config = dependencyConfig.getConfigs().get("queryAwardReceiveList");
        Integer batchSize = Optional.ofNullable(config).map(DependencyConfig.Config::getBatchSize).orElse(50);

        List<List<String>> partitions = Lists.partition(outTradeNoList, batchSize);
        List<QueryAwardReceiveListDTO> result = Lists.newArrayListWithCapacity(outTradeNoList.size());

        for (List<String> partition : partitions) {
            if (config != null && config.getPermitsPerSecond() != null) {
                QUFA_QUERYAWARDRECEIVELIST_RATELIMITER.setRate(config.getPermitsPerSecond());
                QUFA_QUERYAWARDRECEIVELIST_RATELIMITER.acquire();
                log.info("调用/api/open/award/awardReceiveListByOutTradeNos接口，当前限流{}qps",
                        QUFA_QUERYAWARDRECEIVELIST_RATELIMITER.getRate());
            }

            try {
                QueryAwardReceiveListRequest request = new QueryAwardReceiveListRequest()
                        .setOutTradeNo(partition);
                List<QueryAwardReceiveListDTO> receiveListDTO = quFaHttpUtil
                        .postList(QuFaHttpConstant.QUERY_AWARD_RECEIVE_LIST, signReq(request),
                                QueryAwardReceiveListDTO.class);
                if (receiveListDTO != null && CollectionUtil.isNotEmpty(receiveListDTO)) {
                    result.addAll(receiveListDTO);
                }
            } catch (Exception e) {
                log.error("调用/api/open/award/awardReceiveListByOutTradeNos接口失败：", e);
            }
        }
        return result;
    }
}
